package game.service;

import com.sghd.common.utils.ManagedException;
import data.service.DataService;
import game.dic.TishiManager;
import game.model.*;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import network.NetServer;
import network.SocketEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import static network.ServerHandler.PLAYER_KEY;

/**
 * @author fank
 * @date 2018-08-18 14:04
 * @desc 游戏服务
 **/
@Component
public class GameService {

    private Logger logger = LoggerFactory.getLogger(getClass());
    /**玩家缓存*/
    private ConcurrentMap<Long, PlayerService> players = new ConcurrentHashMap();
    /**房间列表*/
    private ConcurrentMap<Integer, RoomService> rooms = new ConcurrentHashMap<>();

    @Autowired
    private DataService dataService;
    @Autowired
    private ConfigService configService;

    @PostConstruct
    void init() {
        ConcurrentMap<Integer, ConfigRoom> configs = configService.getConfigRooms();
        configs.forEach((roomId, configRoom) -> {
            rooms.put(roomId, new RoomService(configRoom, dataService, this));
            if (logger.isInfoEnabled()) {
                logger.info("[{}]初始化成功，桌子数-> {}", configRoom.getRoomName(), configRoom.getDeskCount());
            }
        });
    }

    public String conn(Channel channel, ConneReq request) throws Exception {
        long playerId = request.getPlayerId();
        //boolean success = dataService.checkToken(request.getPlayerId(), request.getToken(), request.getPub(), request.getPlatformId());
        boolean success = true;
        if (success) {//token成功
            //绑定玩家id
            channel.attr(PLAYER_KEY).set(playerId);
            if (players.containsKey(request.getPlayerId())) {
                PlayerService prev = players.get(playerId);
                logger.debug("踢除上一个玩家下线");
                if (prev.isOnline()) {
                    exit(prev);//强制退出游戏
                    Channel prevChannel = prev.getChannel();
                    sendMessage(prevChannel, TishiManager.Tishi_SecondLogin, SocketEnum.infoI);
                    prevChannel.attr(PLAYER_KEY).set(null);
                    prevChannel.close();//关闭链路
                }
            }
        } else {
            throw new ManagedException(-1, "签名验证失败！");
        }
        return "";
    }

    /**
     * 进入房间
     * */
    public void joinRoom(ChannelHandlerContext ctx, long playerId, int configId) throws Exception {
        ConfigRoom configRoom = configService.getConfigRooms().get(configId);
        int roomId = configRoom.getRoomId();
        DeskPlayer deskPlayer = dataService.getPlayeInfo(playerId);
        synchronized (deskPlayer) {//防止同一个玩家多次进入游戏房间
            if (players.containsKey(playerId)) {//已经进入房间
                sendMessage(ctx.channel(), TishiManager.Tishi_T_JoinRoom_Fail, SocketEnum.infoI);
                ctx.close();
                return;
            }
            PlayerService playerService = new PlayerService(deskPlayer, ctx.channel(), roomId);
            RoomService roomService = rooms.get(roomId);
            roomService.joinRoom(playerService);
            players.put(playerId, playerService);
        }
    }

    /**
     *开始游戏
     */
    public void begin_Receive(long playerId, int betIdx) {
        PlayerService playerService = players.get(playerId);
        if (playerService == null) {
            new ManagedException(-1, "玩家不存在!");
        }
        //玩家所在房间
        RoomService roomService = rooms.get(playerService.getRoomId());
        roomService.begin(playerService, betIdx);
    }

    /**
     * 选择一张卡牌
     * */
    public void select(long playerId, int index) {
        PlayerService playerService = players.get(playerId);
        if (playerService == null) {
            new ManagedException(-1, "玩家不存在!");
        }
        //玩家所在房间
        RoomService roomService = rooms.get(playerService.getRoomId());
        roomService.select(playerService, index);
    }

    public void exit(PlayerService playerService) {
        if (playerService == null) {
            return;
        }
        try {
            RoomService roomService = rooms.get(playerService.getRoomId());//玩家所在房间
            roomService.leaveRoom(playerService);
            players.remove(playerService.getPlayerId());
        } catch (Exception e) {
            logger.error("玩家离开游戏发生未知错误!", e);
        } finally {
            playerService = null;
        }
    }

    public void removePlayer(long playerId) {
        players.remove(playerId);
    }

    public void exit(long playerId) {
        PlayerService playerService = players.get(playerId);
        exit(playerService);
    }

    private void sendMessage(Channel channel, String message, int code) {
        channel.writeAndFlush(Unpooled.copiedBuffer((code + NetServer.MSG_SPLIT + message + NetServer.MSG_END).getBytes()));
    }

    public ConcurrentMap<Long, PlayerService> getPlayers() {
        return players;
    }

    public ConcurrentMap<Integer, RoomService> getRooms() {
        return rooms;
    }
}
